package com.baoy.cloud.xxx.sso.shiro.session;

import com.baoy.cloud.xxx.common.Constant;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.session.Session;
import org.apache.shiro.session.UnknownSessionException;
import org.apache.shiro.session.mgt.ValidatingSession;
import org.apache.shiro.session.mgt.eis.AbstractSessionDAO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Set;
import java.util.concurrent.TimeUnit;

@Setter
@Slf4j
public class RedisSessionDao extends AbstractSessionDAO {


    @Autowired
    RedisTemplate redisTemplate;

    @Override
    protected Serializable doCreate(Session session) {
        Serializable sessionId = generateSessionId(session);
        assignSessionId(session, sessionId);
        String sessionJson = SerializableUtils.serialize(session);
        if (log.isDebugEnabled()) {
            log.debug("doCreate {} session - key : {} - value : {}",
                    StringUtils.center("", 80, ">"), sessionId, sessionJson);
        }
        redisTemplate.opsForValue().set(Constant.getShiroSessionId(sessionId.toString()),
                sessionJson, session.getTimeout(), TimeUnit.MILLISECONDS);
        return sessionId;
    }

    @Override
    protected Session doReadSession(Serializable sessionId) {
        String sessionJson = (String) redisTemplate.opsForValue()
                .get(Constant.getShiroSessionId(sessionId.toString()));
        if (log.isDebugEnabled()) {
            log.debug("doReadSession {} session - key : {} - value : {}",
                    StringUtils.center("", 80, ">"), sessionId, sessionJson);
        }
        return SerializableUtils.deserialize(sessionJson);
    }

    @Override
    public void update(Session session) throws UnknownSessionException {
        if (session instanceof ValidatingSession && !((ValidatingSession) session).isValid()) {
            return;
        }
        String sessionId = session.getId().toString();
        if (log.isDebugEnabled()) {
            log.debug("doUpdate {} session - key : {}",
                    StringUtils.center("", 80, ">"), sessionId);
        }
        redisTemplate.opsForValue()
                .set(Constant.getShiroSessionId(sessionId), SerializableUtils.serialize(session),
                        session.getTimeout(), TimeUnit.MILLISECONDS);
    }

    @Override
    public void delete(Session session) {
        String sessionId = session.getId().toString();
        if (log.isDebugEnabled()) {
            log.debug("doUpdate {} session - key : {}",
                    StringUtils.center("", 80, ">"), sessionId);
        }
        redisTemplate.delete(Constant.getShiroSessionId(sessionId));
    }

    @Override
    public Collection<Session> getActiveSessions() {
        Collection<Session> list = new ArrayList<Session>();
        Set<String> keys = redisTemplate.keys(Constant.SESSION_PREFFIX + "*");
        for (String key : keys) {
            Session session = (Session) redisTemplate.opsForValue().get(key);
            if (session != null) {
                list.add(session);
            }
        }
        return list;
    }


}
